﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Linq.Expressions;
using XYAC.Framework.MonitorTireMaterialOnline.Entities;
using XYAC.Framework.MonitorTireMaterialOnline.Extensions;
using XYAC.Framework.MonitorTireMaterialOnline.IServices;

namespace XYAC.Framework.MonitorTireMaterialOnline.Services
{
    /// <summary>
    /// 服务基类
    /// </summary>
    public class ServiceBase<TType, TContext> : IServiceBase<TType, TContext>
        where TType : IEquatable<TType>, new()
        where TContext : DbContext
    {
        public ServiceBase(IOptionsMonitor<AppConfig> appConfig, ILogger logger, IServiceProvider provider)
        {
            //var dbPath = System.IO.Path.GetFullPath(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(this.GetType().Assembly.Location), appConfig.LocalDbPath));
            //this.DB = new SQLiteConnection(dbPath);
            this.Provider = provider;
            this.AppConfig = appConfig;
            this.Logger = logger;

        }

        //public SQLiteConnection DB { get; protected set; }
        //public AppConfig AppConfig { get; }
        public ILogger Logger { get; }
        //public TContext? DB { get; }
        protected IServiceProvider Provider { get; }
        public IOptionsMonitor<AppConfig> AppConfig { get; }




        /// <summary>
        /// 获取所有EntityBase数据
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <returns></returns>
        public IEnumerable<T> GetAll<T>(params Expression<Func<T, bool>>[] filterCondition) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                try
                {
                    IQueryable<T> data = DB.Set<T>();
                    foreach (var filter in filterCondition)
                    {
                        data = data.Where(filter);
                    }
                    return data.ToList();

                }
                catch (Exception ex)
                {
                    Logger.LogError(ex.Message, ex);
                    return Enumerable.Empty<T>();
                }
            }
        }

        /// <summary>
        /// 分页获取数据(Common)
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="pageIndex">页索引</param>
        /// <param name="pageSize">页行数</param>
        /// <param name="filterConditions">过滤条件</param>
        /// <param name="orderConditions">排序条件</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public IEnumerable<T> GetPage<T>(
     int pageIndex,
     int pageSize,
     List<Expression<Func<T, bool>>> filterConditions = null,
     List<(Expression<Func<T, object>> KeySelector, bool Descending)> orderConditions = null)
     where T : class, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                IQueryable<T> data = DB.Set<T>();

                // 应用过滤条件
                if (filterConditions != null)
                {
                    foreach (var condition in filterConditions)
                    {
                        data = data.Where(condition);
                    }
                }

                // 应用排序条件
                bool isOrdered = false;

                if (orderConditions != null && orderConditions.Any())
                {
                    foreach (var (KeySelector, Descending) in orderConditions)
                    {
                        if (!isOrdered)
                        {
                            data = Descending ? data.OrderByDescending(KeySelector) : data.OrderBy(KeySelector);
                            isOrdered = true;
                        }
                        else
                        {
                            var orderedData = (IOrderedQueryable<T>)data;
                            data = Descending ? orderedData.ThenByDescending(KeySelector) : orderedData.ThenBy(KeySelector);
                        }
                    }
                }

                // 确保 pageIndex 为非负数，且 pageSize 为正数
                if (pageIndex < 0)
                    throw new ArgumentOutOfRangeException(nameof(pageIndex), "pageIndex 必须为非负数。");
                if (pageSize <= 0)
                    throw new ArgumentOutOfRangeException(nameof(pageSize), "pageSize 必须为正数。");

                return data.Skip(pageIndex * pageSize).Take(pageSize).ToList();
            }
        }

        /// <summary>
        /// 获取主键数据(Common)
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="id">主键ID</param>
        /// <returns></returns>
        public T GetById<T>(TType id) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                try
                {
                    return DB.Set<T>().FirstOrDefault(e => e.ID.Equals(id));

                }
                catch (Exception ex)
                {
                    Logger.LogError(ex.Message, ex);

                    return default(T);
                }
            }
        }

        /// <summary>
        /// 删除数据(Common)
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="id">主键ID</param>
        /// <returns></returns>
        public bool Delete<T>(TType id) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                int ret = 0;

                using (var trans = DB.Database.BeginTransaction())
                {

                    try
                    {
                        var entity = DB.Set<T>().FirstOrDefault(e => e.ID.Equals(id));
                        DB.Remove(entity);
                        var tempRet = DB.SaveChanges();
                        trans.Commit();
                        ret = tempRet;
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        Logger.LogError(ex.Message, ex);

                    }
                }


                return ret > 0;
            }
        }

        public bool Delete<T>(TType[] ids) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                int ret = 0;

                using (var trans = DB.Database.BeginTransaction())
                {
                    try
                    {

                        var entity = DB.Set<T>().Where(e => ids.Equals(e.ID)).ToList();
                        DB.Remove(entity);
                        var retRet = DB.SaveChanges();
                        trans.Commit();
                        ret = retRet;
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        Logger.LogError(ex.Message, ex);

                    }
                }

                return ret == ids.Length;
            }
        }


        /// <summary>
        /// 新增实体
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="obj">主键ID</param>
        /// <returns></returns>
        public bool Add<T>(T obj) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                int ret = 0;
                using (var trans = DB.Database.BeginTransaction())
                {
                    try
                    {
                        DB.Add(obj);
                        var tempRet = DB.SaveChanges();
                        trans.Commit();
                        ret = tempRet;
                    }
                    catch (Exception ex)
                    {

                        trans.Rollback();
                        Logger.LogError(ex.Message, ex);

                    }
                }
                return ret > 0;
            }
        }

        public IEnumerable<T> GetAll<T>() where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                try
                {


                    return DB.Set<T>().ToList();

                }
                catch (Exception ex)
                {
                    Logger.LogError(ex.Message, ex);

                    return Enumerable.Empty<T>();
                }
            }
        }
        public IEnumerable<T2> GetDistinct<T, T2>(Func<T, T2> expression) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var db = scope.ServiceProvider.GetService<TContext>();
                return db.Set<T>().Select(expression).Distinct().ToList();
            }
        }

        public bool Update<T>(T obj) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                int ret = 0;
                using (var trans = DB.Database.BeginTransaction())
                {

                    try
                    {
                        DB.Update(obj);
                        var tempRet = DB.SaveChanges();
                        trans.Commit();
                        ret = tempRet;
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        Logger.LogError(ex.Message, ex);

                    }
                }

                return ret > 0;
            }
        }
        public int GetCount<T>(Expression<Func<T, bool>> filterCondition = null) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                if (filterCondition != null)
                    return DB.Set<T>().Count(filterCondition);
                return DB.Set<T>().Count();

            }
        }

        public bool Delete<T>(IEnumerable<T> preDeleteData) where T : EntityBase<TType>, new()
        {
            using (var scope = this.Provider.CreateScope())
            {
                var DB = scope.ServiceProvider.GetService<TContext>();
                int ret = 0;
                using (var trans = DB.Database.BeginTransaction())
                {

                    try
                    {
                        var tempRet = 0;
                        //foreach (var item in preDeleteData)
                        DB.RemoveRange(preDeleteData);

                        tempRet = DB.SaveChanges();
                        trans.Commit();
                        ret = tempRet;
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        Logger.LogError(ex.Message, ex);

                    }
                }

                return ret == preDeleteData.Count();
            }
        }
    }
}
